package com.extractor;

import com.gui.Mas;

import javax.swing.*;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 * User: SeedMiner
 * Date: Jun 28, 2010
 * Time: 9:11:36 PM
 * To change this template use File | Settings | File Templates.
 */
public class DataExtractor {
    public Mas mas;
    String outCSVCoulumns = "";
    String outData = "";
    ArrayList mask;
    Map<Object, String> map = new HashMap<Object, String>();
    int STYLEColumnIndex;
    int CWColumnIndex;
    int FilteredSTYLEColumnIndex;
    int FilteredCWColumnIndex;
    String STYLECOLUMNLABLE = "STYLE";
    String CWCOLUMNLABLE = "CW";
    JTable table;
    ArrayList<FabricData> fabricTable=new ArrayList<FabricData>();
    ArrayList<FabricData> fabricCostingValues;
    private int rand;
    private static final String FABRIC_CONF_PATH = "fabric_type_config.conf";


    public DataExtractor() {
        //mas = new MAS();
    }

    public String commaDelimittedToTabDelimitted(String str) {
        String out = "";
        Stack<Character> s = new Stack<Character>();
        char[] chars = str.toCharArray();
        for (char aChar : chars) {
            if (s.empty() && '"' == aChar) {
                s.push(aChar);
            } else if (!s.empty()) {
                if ('"' == aChar) {
                    s.pop();
                } else if (',' != aChar) {
                    out += aChar;
                }
            } else if (',' != aChar) {
                out += aChar;
            } else {
                out += "\t";
            }
        }
        return out;
    }

    public void ExtractData(String path) {
        try {
            FileInputStream fstream = new FileInputStream(path);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            int i = 0;
            String[] colums = mas.colums.getText().split(",");
            String line1 = "";
            String line2 = "";
            //System.out.println(mas.colums.getText());
            while ((strLine = br.readLine()) != null) {
                //System.out.println(strLine);
                if (notEmptyLine(strLine)) {
                    strLine = commaDelimittedToTabDelimitted(strLine);
                    //System.out.println(strLine);
                    if (i == 0) {
                        //System.out.println(strLine);
                        line1 = strLine;
                    } else if (i == 1) {
                        line2 = strLine;
                        mask = createMask(colums, line1.split("\t"), line2.split("\t"));
                        //System.out.println(outCSVCoulumns);
                    } else if (1 < i) {
                        //System.out.println(strLine);
                        createDataLine(strLine.split("\t"), mask);
                    }
                    i++;
                }
            }
            //System.out.println(outCSVCoulumns);
            //System.out.println(outData);
            writeFilteredDataToFile();
            createPanelToGetUserInputs();
            in.close();
        } catch (Exception e) {//Catch exception if any
            System.err.println("Error: " + e.getMessage());
        }
    }

    private void createPanelToGetUserInputs() {
        ArrayList keys = new ArrayList();
        Set set = new HashSet();
        for (Object key : map.keySet()) {
            DataKey dk = (DataKey) key;
            set.add(dk.STYLE);
        }
        keys.addAll(set);
        Collections.sort(keys);
        String[] columnNames = {"Style", "Costing Value", "Fabric Type",};
        int rows = keys.size();
        String[][] data = new String[rows][3];
        for (int i = 0; i < rows; i++) {
            data[i][0] = keys.get(i).toString();
        }
        table = new JTable(data, columnNames);
        JScrollPane scrollPane = new JScrollPane(table);
        table.setFillsViewportHeight(true);
        mas.userInputFabricType.add(scrollPane);
        mas.userInputFabricType.updateUI();
    }

    private void writeFilteredDataToFile() {
        try {
            FileWriter fstream1 = new FileWriter("out.csv");
            BufferedWriter out = new BufferedWriter(fstream1);
            out.write(outCSVCoulumns + "\n");
            ArrayList values = new ArrayList();
            values.addAll(map.values());
            Collections.sort(values);
            Iterator it = values.iterator();
            while (it.hasNext()) {
                out.write(it.next().toString());
            }
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void createDataLine(String[] strings, ArrayList mask) {
        String line = "";
        for (int i = 0; i < mask.size(); i++) {
            int index = new Integer(mask.get(i).toString());
            line += strings[index];
            if (i + 1 != mask.size()) {
                line += ",";
            }
        }
        line += "\n";
        outData += line;
        DataKey dk = new DataKey(strings[STYLEColumnIndex], strings[CWColumnIndex]);
        if (!map.containsKey(dk)) {
            map.put(dk, line);
        } else {
            //System.out.println(line);
            String stringInTheMap = map.get(dk);
            String[] addArgument1 = stringInTheMap.split(",");
            String[] addArgument2 = line.split(",");
            map.put(dk, addValuesHavingSameKeys(addArgument1, addArgument2));
        }
        //System.out.println(line);
    }

    private String addValuesHavingSameKeys(String[] a, String[] b) {
        String result = "";
        for (int i = 0; i < a.length; i++) {
            if (i != FilteredSTYLEColumnIndex && i != FilteredCWColumnIndex && !"\n".equals(a[i])) {
                int num1 = -1;
                int num2 = -1;
                try {
                    if (!"".equals(a[i])) {
                        num1 = Integer.valueOf(a[i]);
                    }
                    if (!"".equals(b[i])) {
                        num2 = Integer.valueOf(b[i]);
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
                if (num1 != -1 && num2 != -1) {
                    result += num1 + num2;
                } else if (num1 == -1 && num2 != -1) {
                    result += num2;
                } else if (num1 != -1 && num2 == -1) {
                    result += num1;
                }

            } else {
                result += a[i];
            }
            if (i + 1 != a.length) {
                result += ",";
            }
        }
        return result;
    }

    private ArrayList createMask(String[] columsToFilter, String[] columns1, String[] columns2) {
        ArrayList mask = new ArrayList();
        int columsnumber = (columns1.length < columns2.length) ? columns2.length : columns1.length;
        for (int j = 0; j < columsToFilter.length; j++) {
            String comp = columsToFilter[j].trim();
            for (int i = 0; i < columsnumber; i++) {
                if (i < columns1.length) {
                    String s1 = columns1[i].trim();
                    if (s1.equalsIgnoreCase(comp)) {
                        mask.add(i);
                        outCSVCoulumns += s1;
                        if (j + 1 != columsToFilter.length) {
                            outCSVCoulumns += ",";
                        }
                        break;
                    }
                }
                if (i < columns2.length) {
                    String s2 = columns2[i].trim();
                    if (s2.equals(STYLECOLUMNLABLE)) {
                        STYLEColumnIndex = i;
                    } else if (s2.equals(CWCOLUMNLABLE)) {
                        CWColumnIndex = i;
                    }
                    if (s2.equalsIgnoreCase(comp)) {
                        mask.add(i);
                        outCSVCoulumns += s2;
                        if (j + 1 != columsToFilter.length) {
                            outCSVCoulumns += ",";
                        }
                        break;
                    }
                }
            }
        }
        //Collections.sort(mask);
        findFilteredColumnIndices(outCSVCoulumns);
        return mask;
    }

    private void findFilteredColumnIndices(String s) {
        String[] sarray = s.split(",");
        for (int i = 0; i < sarray.length; i++) {
            if (STYLECOLUMNLABLE.equals(sarray[i])) {
                FilteredSTYLEColumnIndex = i;
            } else if (CWCOLUMNLABLE.equals(sarray[i])) {
                FilteredCWColumnIndex = i;
            }
        }
    }

    public boolean notEmptyLine(String line) {
        Pattern p = Pattern.compile("[\\s]");
        String[] result = p.split(line);
        return 1 < result.length;
    }

    public Object[] getTopics(String line) {
        String[] arr = line.split(",");
        ArrayList al = new ArrayList();
        for (int i = 0; i < arr.length; i++) {
            if (0 < arr[i].length())
                al.add(arr[i]);
        }
        return al.toArray();
    }

    public void calculateRatiosAndSaveOutput() {
        try {
            FileWriter fstream1 = new FileWriter("outRatios.csv");
            BufferedWriter out = new BufferedWriter(fstream1);
            out.write(outCSVCoulumns + "\n");

            AlgorithmMAS am = new AlgorithmMAS();

            ArrayList values = new ArrayList();
            values.addAll(map.values());
            Collections.sort(values);
            Iterator it = values.iterator();
            while (it.hasNext()) {
                String production = it.next().toString();
                //out.write(it.next().toString());
                //am.findRatios(getNumberOfPiles(production), getMaxRatioSum(production), getProduction(production));
                ArrayList<Integer> product = getProduction(production/*"388883,44,11,17,3" + '\n'*/);
                /*if (emptyLine(product)) {
                    out.write(production);
                    continue;
                }*/
                //RatioOutputs r0 = am.findRatios(getRandPiles(), getRandMaxRatioSum(), getStyle(production), getCW(production), product);
                RatioOutputs r0 = am.findRatios(getNumberOfPiles(production), getMaxRatioSum(production), getStyle(production), getCW(production), product);
                if (r0.finished) {
                    out.write(production);
                    if (r0.ratios1 != null) {
                        out.write("Pile Size: " + r0.piles1 + ",," + getStringVal(r0.ratios1) + "\n");
                    }
                    if (r0.ratios2 != null) {
                        out.write("Pile Size: " + r0.piles2 + ",," + getStringVal(r0.ratios2) + "\n");
                    }
                    if (r0.ratios3 != null) {
                        out.write("Pile Size: " + r0.piles3 + ",," + getStringVal(r0.ratios3) + "\n");
                    }
                    if (r0.ratios4 != null) {
                        out.write("Pile Size: " + r0.piles4 + ",," + getStringVal(r0.ratios4) + "\n");
                    }
                    out.write("_______\n");
                } else {
                    out.write(production);
                    out.write("EXCEPTIONAL CASE!!!\n");
                }

            }
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean emptyLine(ArrayList<Integer> product) {
        boolean result = true;
        for (int val : product) {
            result = val == AlgorithmMAS.K;
            if (!result) break;
        }
        return result;
    }

    private String getCW(String production) {
        return production.split(",")[1];
    }

    private String getStyle(String production) {
        return production.split(",")[0];
    }

    private String getStringVal(ArrayList<Integer> ratios1) {
        String s = "";
        for (int i = 0; i < ratios1.size(); i++) {
            int val = ratios1.get(i);
            if (val == AlgorithmMAS.K) {
                s += ",";
            } else {
                s += val + ",";
            }
        }
        return s;
    }

    public static ArrayList<Integer> getProduction(String production) {

        String[] prod = production.split(",");
        ArrayList qtt = new ArrayList();
        int X = prod.length;
        for (int i = 2; i < X; i++) {
            String value = "";
            if (i == X - 1) {
                char[] chars = prod[i].toCharArray();
                for (char c : chars) {
                    if ('\n' == c) {
                        break;
                    } else {
                        value += c;
                    }
                }
            } else {
                value = prod[i];
            }

            if ("".equals(value)) {
                qtt.add(AlgorithmMAS.K);
            } else {
                qtt.add(Integer.valueOf(value));
            }
        }
        return qtt;
    }

    private int getMaxRatioSum(String production) {
        int style = Integer.valueOf(getStyle(production));
        int fabricType=getFabricTypeFromUserInput(style);
        float costingValue=getCostingValueFromUserInput(style);
        int lengthOfPiece=getLengthOfPieceFromTheFabricConfig(fabricType);
        int maxRatioSum=(int)(lengthOfPiece/costingValue);
        return maxRatioSum;
    }

    private int getNumberOfPiles(String production) {
        int style = Integer.valueOf(getStyle(production));
        int fabricType=getFabricTypeFromUserInput(style);
        int numberOfPiles=getNumberOfPilesFromTheFabricConfig(fabricType);
        return numberOfPiles;
    }

    private int getLengthOfPieceFromTheFabricConfig(int fabricType) {
        FabricData fd = fabricTable.get(fabricType - 1);
        int widthOfPiece = fd.width;
        return widthOfPiece;
    }

    private float getCostingValueFromUserInput(int style) {
        float val = Float.valueOf(table.getModel().getValueAt(0, 1).toString());//get the costing value
        return val;
    }

    private int getFabricTypeFromUserInput(int style) {
        int val = Integer.valueOf(table.getModel().getValueAt(0, 2).toString());//get the fabric type
        return val;
    }

    private int getNumberOfPilesFromTheFabricConfig(int fabricType) {
        FabricData fd = fabricTable.get(fabricType - 1);
        int numberOfPiles = fd.numberOfPiles;
        return numberOfPiles;
    }

    public void createFabricTable() {
        FileInputStream fstream = null;

        try {
            fstream = new FileInputStream(FABRIC_CONF_PATH);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            int i = 0;
            while ((strLine = br.readLine()) != null) {
                i++;
                String[] data = strLine.split(",");
                String fabricName = data[0].trim();
                int lengthOfPiece = Integer.valueOf(data[1].trim());
                int fabricPileSize = Integer.valueOf(data[2].trim());
                fabricTable.add(new FabricData(i, fabricName, lengthOfPiece, fabricPileSize));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }


    public void createFabricCostingValueTable() {
        //table.
    }

    public int getRandPiles() {
        int[] rand = {50, 125, 100};
        int val = (int) (Math.random() * 100) % 3;
        //return rand[val];
        return 50;
    }

    public int getRandMaxRatioSum() {
        int[] rand = {6, 7, 8, 9, 10};
        int val = (int) (Math.random() * 100) % 5;
        //return rand[val];
        return 8;
    }
}
